package com.heima.article.job;
import com.alibaba.fastjson.JSON;
import com.heima.article.service.HotArticleService;
import com.heima.model.common.constants.article.HotArticleConstants;
import com.heima.model.mess.app.AggBehaviorDTO;
import com.heima.model.mess.app.NewBehaviorDTO;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.seata.common.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class UpdateHotArticleJob {
    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    HotArticleService hotArticleService;
    @XxlJob("updateHotArticleJob")
    public ReturnT updateHotArticleHandler(String params){
        log.info("热文章分值更新 调度任务开始执行....");
        //1. 读取最近10s redis 锁缓存的最新文章行为数据集合
        List<NewBehaviorDTO>  newBehaviorDTOList= getRedisBehaviorList();
        if (CollectionUtils.isEmpty(newBehaviorDTOList)){
            log.info("太冷清了这个app");
            return ReturnT.SUCCESS;
        }
        //2.对数据集合统计运算
      List<AggBehaviorDTO> aggBehaviorDTOList=    getAggBehaviorList(newBehaviorDTOList);
        //3.

        // TODO 定时更新文章热度
        aggBehaviorDTOList.forEach(aggBehaviorDTO ->
                hotArticleService.updateApArticle(aggBehaviorDTO)
                );

        log.info("热文章分值更新 调度任务完成....");
        return ReturnT.SUCCESS;
    }

    private List<AggBehaviorDTO> getAggBehaviorList(List<NewBehaviorDTO> newBehaviorDTOList) {
        List<AggBehaviorDTO> aggBehaviorList = new ArrayList<>();
        //1. 按照文章id对行为数据进行分组 Map<文章id,List<NewBehaviorDTO>>
        Map<Long, List<NewBehaviorDTO>> map = newBehaviorDTOList.stream()
                .collect(Collectors.groupingBy(NewBehaviorDTO::getArticleId));
        //2. 循环遍历行为分组,将每一个分组数据 ==> 封装成AggBehaviorDTO对象

        //[{type:VIEWS,add:1}]
        //{adticleId:123,views: , likes: comment: , collect}
            map.forEach((articleId,behaviorList)->{



                Optional<AggBehaviorDTO> reduceResult = behaviorList.stream()
                        .map(behavior -> {
                            AggBehaviorDTO aggBehaviorDTO = new AggBehaviorDTO();
                            aggBehaviorDTO.setArticleId(articleId);
                            switch (behavior.getType()) {
                                case VIEWS:
                                    aggBehaviorDTO.setView(behavior.getAdd());
                                    break;
                                case LIKES:
                                    aggBehaviorDTO.setView(behavior.getAdd());
                                    break;
                                case COMMENT:
                                    aggBehaviorDTO.setView(behavior.getAdd());
                                    break;
                                case COLLECTION:
                                    aggBehaviorDTO.setView(behavior.getAdd());
                                    break;
                            }
                            return aggBehaviorDTO;
                        }).reduce((a1, a2) -> {
                            a1.setView(a1.getView() + a2.getView());
                            a1.setLike(a1.getLike() + a2.getLike());
                            a1.setComment(a1.getComment() + a2.getComment());
                            a1.setCollect(a1.getCollect() + a2.getCollect());
                            return a1;
                        });
                if (reduceResult.isPresent()) {
                    // 聚合结果
                    AggBehaviorDTO aggBehavior = reduceResult.get();
                    log.info("热点文章 聚合计算结果  ===>{}", aggBehavior);
                    aggBehaviorList.add(aggBehavior);
                }

            });

        //3.将AggBehaviorDTO对象收集到一个集合中,返回结果

        return aggBehaviorList;
    }

    /**
     * 获取redis产生的最新
     * @return
     */
    private List<NewBehaviorDTO> getRedisBehaviorList() {
        //1.创建脚本对象
        DefaultRedisScript<List> script = new DefaultRedisScript<>();


        //2.设置返回类型 脚本地址
            script.setResultType(List.class);
            script.setScriptSource(new ResourceScriptSource(new ClassPathResource("redis.lua")));

        //3.执行脚本得到返回结果   list<String>
        List<String> result = redisTemplate.execute(script, Arrays.asList(
                HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_LIST
        ));
        //4.将得到的集合 ,转为List<NewBehaviorDTO>
      return   result.stream()
                .map(jsonStr -> JSON.parseObject(jsonStr,NewBehaviorDTO.class))
                .collect(Collectors.toList());
    }
}